package com.acme.domain.bank;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.acme.domain.account.Account;
import com.acme.domain.account.CheckingAccount;
import com.acme.domain.account.SavingAccount;
import com.acme.exceptions.ClientDuplicateException;
import com.acme.exceptions.ClientNotExistException;
import com.acme.service.bank.ClientRegistrationListener;
import com.acme.service.bank.EmailService;


public class Bank {
	
	private List<Client> clients = new ArrayList<Client>();	
	private List<ClientRegistrationListener> listeners = new ArrayList<ClientRegistrationListener>();
	
	private ClientRegistrationListener debugListener = new DebugListener();
	private EmailNotificationListener emailListener = new EmailNotificationListener();
	
	public final static String regLine = "^accounttype=([cs]);balance=([-+]?[0-9]*\\.?[0-9]*);overdraft=([-+]?[0-9]*\\.?[0-9]*);name=(\\w+);gender=([fm]);$";

	public Bank() {
		listeners.add(new ClientRegistrationListener() {
			
			@Override
			public void onClientAdded(Client c) {
				System.out.println("Client: " + c.getClientSalutation() + ", welcomoe!");
			}
		});
		
		listeners.add(emailListener);
		listeners.add(debugListener);
	}
	
	public class DebugListener implements ClientRegistrationListener{

		@Override
		public void onClientAdded(Client client) {
			System.out.println("Client " + client.getClientSalutation() +" added on " + new java.util.Date());
		}
		
	}
	
	public class EmailNotificationListener implements ClientRegistrationListener{

		@Override
		public void onClientAdded(Client client) {
			Email email = new EmailImpl("Your bank", client.getEmailAddress(), "Salut!", "Welcome on board, Client!");
			EmailService.getEmailService().addEmail(email);			
		}	
		
	}
	
	public void addClient(Client client) throws ClientDuplicateException, ClientNotExistException {
		for (Client c : this.clients) {
			if(client.getName().equals(c.getName())) {
				throw new ClientDuplicateException("Client already exist!");
			}
		}
		clients.add(client);
		for(ClientRegistrationListener l : this.listeners) {
			l.onClientAdded(client);
		}
	}
	
	public void addClient(String str) throws ClientDuplicateException, ClientNotExistException {
		Pattern pattern = Pattern.compile(regLine);
		Matcher matcher = pattern.matcher(str);
		List<Account> accounts = new ArrayList<Account>();
		Gender gender;
		while(matcher.find()) {
			if (matcher.group(1).equals("c")) {
				accounts.add(new CheckingAccount(Double.parseDouble(matcher.group(2)),Double.parseDouble(matcher.group(3))));
			} else {
				accounts.add(new SavingAccount(Double.parseDouble(matcher.group(2))));	
			}
			
			if (matcher.group(matcher.groupCount()) == "f") {
				gender = Gender.FEMALE;
			} else {
				gender = Gender.MALE;
			}
			this.addClient(new Client(accounts, matcher.group(4), gender));
		}
	}
	
	public Client getClient(int id) throws ClientNotExistException {
		if(id >= 0) {
			if(clients.size() > id) {
				return clients.get(id);
			} else {
				throw new ClientNotExistException("Client do not exist!");
			}	
		} else {
			throw new IllegalArgumentException("id incorrect");
		}
	}
	
	public int getClientCount() {
		return this.clients.size();
	}
	public Client getClientByName(final String name) {
		for(Client client : clients) {
			if(name.equals(client.getName())) return client;
		}
		return null;
	}

	@Override
	public String toString() {
		StringBuffer clientsString = new StringBuffer("The bank has: \n");
		for(Client c : clients) {
			clientsString.append(c.toString());
		}
		clientsString.append("At all " + clients.size() + " clients");
		return clientsString.toString();
	}

	public List<Client> getClientsList() {
		return clients;	
	}
	
}
